package com.topfinance.cnaps2.service.impl;

import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;

import com.topfinance.cnaps2.dto.SingleDto;
import com.topfinance.cnaps2.dto.TblTxLineDto;
import com.topfinance.cnaps2.dto.TblTxTraceDto;
import com.topfinance.cnaps2.dto.TxSummaryDto;
import com.topfinance.cnaps2.ebo.TblTxEbo;
import com.topfinance.cnaps2.ebo.msg.MsgPairEbo;
import com.topfinance.cnaps2.service.IMsgMatchManager;
import com.topfinance.frame.dao.HibernateEntityDao;
import com.topfinance.frame.exception.AppException;
import com.topfinance.frame.util.DateUtil;

/**
 * 该类自动实现了dao的一般方法，如add, remove, update
 * 在service中出现的大部分情况下是在向后台提交数据前的处理(如校验)及获取后台数据后的处理等
 * 
 * @author
 * 
 */

public class MsgMatchManagerImpl extends HibernateEntityDao implements IMsgMatchManager {

	private static final Log log = LogFactory.getLog(MsgMatchManagerImpl.class);

	// 获得MsgTree列表
	// type：IBPS/BEPS/HVPS
	// msg：ibps.101.001.01
	// dir：U或者D
	// 返回MsgPairEbo
	public List getMsgMatchList(String type, String msg, String dir) throws AppException {
		String hql = " from MsgPairEbo t ";
		String where = " ";
		where += " t.type = '" + type + "'";
		where += " and t.leftmsg = '" + msg + "'";
		where += " and t.leftdir = '" + dir + "'";
		List<Object> paramList = new ArrayList<Object>();
		if (isNotBlank(where)) {
			where = " where " + where;
		}
		hql = hql + where;
		log.debug("[getMsgMatchList]" + hql);
		return find(hql, paramList.toArray());
	}

	// 获得Match所有列表
	// 返回MsgPairEbo
	public List getMsgMatchListAll() throws AppException {
		String hql = " from MsgPairEbo t ";
		String where = " ";
		List<Object> paramList = new ArrayList<Object>();
		if (isNotBlank(where)) {
			where = " where " + where;
		}
		hql = hql + where;
		return find(hql, paramList.toArray());
	}

	// 获得时间间隔
	// curday格式2010-06-21
	private String[] getCurDayRange(String curday) throws AppException {
		String[] bgnend = new String[2];
		if (curday == null || curday.length() == 0) {
			bgnend[0] = DateUtil.addHour(-16);
			bgnend[1] = DateUtil.addHour(8);
		}else{
			bgnend[0] = DateUtil.addDay(curday,-1);
			bgnend[1] = curday;
		}
		return bgnend;
	}

	// 根据时间戳和txid获得opname
	private String getOpByTxid(String txid,Timestamp ts,boolean max) throws AppException {
		String hql = " from TblTxEbo t ";
		String where = " ";
		where += " t.txId = '" + txid + "'";
		//where += " and t.ts = " + ts;
		if(max)
			where += " order by t.ts desc";
		else
			where += " order by t.ts asc";
		List<Object> paramList = new ArrayList<Object>();
		if (isNotBlank(where)) {
			where = " where " + where;
		}
		hql = hql + where;
		List list = find(hql, paramList.toArray());
		if(list.size() >= 1){
			TblTxEbo t = (TblTxEbo)list.get(0);
			return t.getOpName();
		}
		return null;
	}

	
	// 获得当前时间段交互消息
	// curday格式2010-06-21
	public List getCurMsgList(String curday,String lststamp) throws AppException {
		List list = new ArrayList();
		List msgOpers = new ArrayList();
		if(lststamp != null && lststamp.length()>0){
			//2010-06-22-15:11:14:953
			final String sql = "select distinct tx_id from tbl_audit where ts >  to_timestamp('" +lststamp +"','yyyy-mm-dd-hh24:mi:ss:ff')";
			list = this.getHibernateTemplate().executeFind(new HibernateCallback() {
				public Object doInHibernate(Session session) throws HibernateException, SQLException {
					Query query = session.createSQLQuery(sql);// 创建SESSION
					List list = query.list();// 获取结果
					return list;// 返回值
				}
			});
		}else{
			String[] bgnend = getCurDayRange(curday);
			String bgn = bgnend[0] + "-16:00:00";
			String end = bgnend[1] + "-16:00:00";
			final String sql = "select distinct tx_id from tbl_audit where ts between to_date('"+bgn+"','yyyy-mm-dd-hh24:mi:ss') and to_date('"+end+"','yyyy-mm-dd-hh24:mi:ss')";
			list = this.getHibernateTemplate().executeFind(new HibernateCallback() {
				public Object doInHibernate(Session session) throws HibernateException, SQLException {
					Query query = session.createSQLQuery(sql);// 创建SESSION
					List list = query.list();// 获取结果
					return list;// 返回值
				}
			});
		}
		int size = list.size();
		int paired = 0;
		int total = 0;
		for(Object txid:list){
			String tid = txid.toString();
			final String sql = "select max(ts) maxts,min(ts) mints from tbl_audit where tx_id = '"+tid+"'";
			list = this.getHibernateTemplate().executeFind(new HibernateCallback() {
				public Object doInHibernate(Session session) throws HibernateException, SQLException {
					Query query = session.createSQLQuery(sql);// 创建SESSION
					List list = query.list();// 获取结果
					return list;// 返回值
				}
			});
			if(list.size()==1){
				//maxts,mints
				Object[] tsarray = (Object[])list.get(0);
				String bgnOp = getOpByTxid(tid,(Timestamp)tsarray[1],false);
				String endOp = getOpByTxid(tid,(Timestamp)tsarray[0],true);
				//msgOpers.add(new TblTxTraceDto(bgnOp,endOp,(Timestamp)tsarray[0],(Timestamp)tsarray[1]));
				TblTxTraceDto txtr = new TblTxTraceDto(tid,bgnOp,endOp,(Timestamp)tsarray[0],(Timestamp)tsarray[1]); 
				List line = getMsgLine(tid);
				if(line.size()>0){
					Object o = line.get(line.size()-1);
					if(o instanceof SingleDto){
						SingleDto so = (SingleDto)o;
						txtr.setPaired(so.getName());
						if("true".equals(so.getName()))
							paired++;
					}
				}
				addOper(msgOpers,txtr);
				total++;
			}
		}
		//加上合计信息，只处理存量数据
		if(lststamp == null || lststamp.length()==0){
			TxSummaryDto sum = new TxSummaryDto();
			sum.setTotal(total);
			sum.setPaired(paired);
			sum.setUnpaired(total-paired);
			msgOpers.add(sum);
		}
		return msgOpers;
	}
	
	private synchronized void addOper(List list,TblTxTraceDto tx){
		if(list.size() == 0){
			list.add(tx);
			return;
		}else{
			int size = list.size();
			int pos = 0;
			for(int i=0;i<size;i++){
				TblTxTraceDto t0 = (TblTxTraceDto)list.get(i);
				if(tx.maxTs().after(t0.maxTs()))
					break;
				else
					pos++;
			}
			//add Empty Object
			list.add(null);
			for(int i=size-1;i>=pos;i--)
				list.set(i+1, list.get(i));
			list.set(pos, tx);
		}
	}

	// 获得交易交换明细
	public List getMsgLine(String txid) throws AppException{
		String hql = " from TblTxEbo t ";
		String where = " ";
		where += " t.txId = '" + txid + "'";
		where += " order by t.ts asc";
		List<Object> paramList = new ArrayList<Object>();
		if (isNotBlank(where)) {
			where = " where " + where;
		}
		boolean paired = true;
		hql = hql + where;
		List list = find(hql, paramList.toArray());
		int size = list.size();
		TblTxLineDto preLine = null;
		TblTxLineDto curLine = null;
		for(int i=0;i<size;i++){
			TblTxEbo t = (TblTxEbo)list.get(i);
			curLine = new TblTxLineDto(t.getOpName(),t.getTs(),t.getDirection(),t.getHost(),t.getPartner(),t.getStatus());
			paired = checkTxLine(preLine,curLine)&&paired;
			list.set(i, curLine);
			preLine = curLine;
		}
		//是否完全匹配
		paired = checkTxLine(curLine,curLine)&&paired;
		//最后一行返回交易是否匹配完成的标志，UI不做现实处理。
		list.add(new SingleDto(Boolean.toString(paired)));
		return list;
	}

	// 获得交易匹配规则
	private boolean checkTxLine(TblTxLineDto preLine,TblTxLineDto curLine) throws AppException{
		//第一行不检查
		if(preLine == null)
			return true;
		List list = getMsgPairDef(preLine.getOper(),preLine.getDir());
		//提示后续消息
		String hint = "";
		boolean paired = false;
		for(Object po:list){
			MsgPairEbo p = (MsgPairEbo)po;
			hint += p.getMemo() + ",";
			if(curLine.getOper().equals(p.getRightmsg()) &&curLine.getDir().equals(p.getRightdir())){
				curLine.setDesc(p.getMemo());
				curLine.setPaired("Y");
				paired = true;
				break;
			}else if(p.getRightmsg() == null ||p.getRightmsg().length() == 0){
				curLine.setPaired("Y");
				paired = true;
				break;
			}
		}
		//如果没有匹配上，给出可能的提示
		if(!paired){
			hint = hint.substring(0,hint.length()-1);
			preLine.setDesc("[期望]" + hint);
		}
		return paired;
	}
	
	// 获得交易匹配规则
	private List<MsgPairEbo> getMsgPairDef(String oper,String dir) throws AppException{
		String hql = " from MsgPairEbo t ";
		String where = " ";
		where += " t.leftmsg = '" + oper + "'";
		where += " and t.leftdir = '" + dir + "'";
		List<Object> paramList = new ArrayList<Object>();
		if (isNotBlank(where)) {
			where = " where " + where;
		}
		hql = hql + where;
		log.debug("[getMsgMatchList]" + hql);
		return find(hql, paramList.toArray());
	}
	
}
